package edu.study.common.util.ftp;

import com.jcraft.jsch.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;


@Deprecated
public class ScpUtil {
    private static Logger logger = LoggerFactory.getLogger(ScpUtil.class);

    public static boolean upload(ScpBean bean, String remoteFilePath, FileInputStream fis) {
        if (StringUtils.isBlank(remoteFilePath)) {
            logger.warn("远程文件地址不能为空");
            return false;
        }
        if (fis == null) {
            logger.warn("本地文件流对象为空");
            return false;
        }
        if (!bean.validate()) {
            logger.warn("登陆远程服务器配置信息校验失败");
            return false;
        }
        Session session = null;
        Channel channel = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(bean.getUsername(), bean.getRemoteAddress(), bean.getRemotePort());

            ScpUserInfo userInfo = new ScpUserInfo(bean.getPassword());
            session.setUserInfo(userInfo);
            session.connect();

            String command = "scp  -t " + remoteFilePath;
            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);

            OutputStream out = channel.getOutputStream();
            InputStream in = channel.getInputStream();

            channel.connect();
            if (checkAck(in) != 0) {
                throw new Exception("标准输入流读取出错！");
            }
            long filesize = fis.available();
            command = "C0644 " + filesize + " ";
            command = command + "\n";
            out.write(command.getBytes());
            out.flush();
            if (checkAck(in) != 0) {
                throw new Exception("标准输入流读取出错");
            }
            byte[] buf = new byte['?'];
            for (; ; ) {
                int len = fis.read(buf, 0, buf.length);
                if (len <= 0) {
                    break;
                }
                out.write(buf, 0, len);
            }
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();
            if (checkAck(in) != 0) {
                throw new Exception("标准输入流读取出错");
            }
            out.close();
            in.close();
        } catch (JSchException e) {
            logger.warn("Scp文件上传失败，JSchException：", e.getMessage());
            return false;
        } catch (IOException e) {
            logger.warn("Scp文件上传失败，IOException：", e.getMessage());
            return false;
        } catch (Exception e) {

            logger.warn("Scp文件上传失败，Exception：", e.getMessage());
            return false;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                    fis = null;
                } catch (Exception e) {
                    logger.error("关闭输入流发生异常", e);
                }
            }
            if ((session != null) && (session.isConnected())) {
                session.disconnect();
            }
        }
        return true;
    }

    public static boolean download(ScpBean bean, String remoteFilePath, FileOutputStream fos) {
        if (StringUtils.isBlank(remoteFilePath)) {
            logger.warn("远程文件地址不能为空");
            return false;
        }
        if (fos == null) {
            logger.warn("本地文件流对象为空");
            return false;
        }
        if (!bean.validate()) {
            logger.warn("登陆远程服务器配置信息校验失败");
            return false;
        }
        Session session = null;
        Channel channel = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(bean.getUsername(), bean.getRemoteAddress(), bean.getRemotePort());

            ScpUserInfo userInfo = new ScpUserInfo(bean.getPassword());
            session.setUserInfo(userInfo);
            session.connect();

            channel = session.openChannel("exec");
            String command = "scp -f " + remoteFilePath;
            ((ChannelExec) channel).setCommand(command);

            OutputStream out = channel.getOutputStream();
            InputStream in = channel.getInputStream();

            channel.connect();

            byte[] buf = new byte['?'];
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();
            for (; ; ) {
                int c = checkAck(in);
                if (c != 67) {
                    break;
                }
                in.read(buf, 0, 5);

                long filesize = 0L;
                while (in.read(buf, 0, 1) >= 0) {
                    if (buf[0] == 32) {
                        break;
                    }
                    filesize = filesize * 10L + (buf[0] - 48);
                }
                for (int i = 0; ; i++) {
                    in.read(buf, i, 1);
                    if (buf[i] == 10) {
                        break;
                    }
                }
                buf[0] = 0;
                out.write(buf, 0, 1);
                out.flush();
                for (; ; ) {
                    int foo;
                    if (buf.length < filesize) {
                        foo = buf.length;
                    } else {
                        foo = (int) filesize;
                    }
                    foo = in.read(buf, 0, foo);
                    if (foo >= 0) {
                        fos.write(buf, 0, foo);
                        filesize -= foo;
                        if (filesize == 0L) {
                            break;
                        }
                    }
                }
                if (checkAck(in) != 0) {
                    throw new Exception("文件流未被完整读取");
                }
                buf[0] = 0;
                out.write(buf, 0, 1);
                out.flush();
            }
            in.close();
            out.close();
        } catch (JSchException e) {
            logger.warn("Scp文件下载失败，JSchException ", e.getMessage());
            return false;
        } catch (IOException e) {
            logger.warn("Scp文件下载失败，IOException ", e.getMessage());
            return false;
        } catch (Exception e) {
            logger.warn("Scp文件下载失败，Exception ", e.getMessage());
            return false;
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                    fos = null;
                } catch (IOException e) {
                    logger.error("输出流关闭发生异常", e);
                }
            }
            if ((session != null) && (session.isConnected())) {
                session.disconnect();
            }
        }
        return true;
    }

    private static int checkAck(InputStream in) throws IOException {
        int b = in.read();
        if (b == 0) {
            return b;
        }
        if (b == -1) {
            return b;
        }
        if ((b == 1) || (b == 2)) {
            StringBuilder sb = new StringBuilder();
            int c;
            do {
                c = in.read();
                sb.append((char) c);
            } while (c != 10);
            if (b == 1) {
                System.out.print(sb.toString());
            }
            if (b == 2) {
                System.out.print(sb.toString());
            }
        }
        return b;
    }
}
